﻿#include "bt_at_cmd.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/system_properties.h>
#include <android/log.h>
#include <poll.h>

#define TAG "xqCarplay_at"
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__)

#define MAX_COMMAND_LENGTH 1024*4
static unsigned char iap_count = 0;
static char iap_buffer[MAX_COMMAND_LENGTH] = { 0 };
static int s_client_id = -1;
static volatile int iap_running = 1;
static volatile int iap_socket_running = 1;

#define MAX_BT_INFO 1024
#define IAP_UUID "00000000DECAFADEDECADEAFDECACAFE"
char g_local_name[MAX_BT_INFO] = { 0 };
char g_local_addr[MAX_BT_INFO] = { 0 };
char g_local_dev_id[MAX_BT_INFO] = { 0 };
char g_pair_addr[MAX_BT_INFO] = { 0 };
char g_bt_version[MAX_BT_INFO] = { 0 };
char g_remote_addr[MAX_BT_INFO] = { 0 };
char g_remote_name[MAX_BT_INFO] = { 0 };
char g_remote_phone_uuid[MAX_BT_INFO] = { 0 };
char g_bt_status = 0; //0,disconnect 1,connected
char g_iap_status = 0; //0,disconnect 1,connected 2 connectting
char g_support_iap = 0; //0,no  1,support
char g_iap_uuid_status = 0; //1,start, 0, end
char g_pair_status = 0; //0,pair failed,1,pair success
char g_AA_rfcomm_status = 0;

static volatile int iap_rfcomm_socket = -1;

extern void connect_carplay_wl(char mac[6], char *local_mac, char bt_iap);
extern void connect_androidauto_wl(char mac[6], char *local_mac, char bt_iap);
extern void on_bluetooth_connect_state(int state);
extern void on_phone_bluetooth_name(char*name);
extern int carplay_readIap2DataProc(char *buf, int len);
extern int androidauto_readIap2DataProc(char *buf, int len);

int connect_iap(char *bd);
int send_iap_data_socket(char *data, int data_len);
int disconnect_iap();
int write_at_cmd(char *data);
int open_iap_rfcomm();
//int open_bt_uart();
void init_time(int time);
int close_iap_rfcomm();

typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned long UINT32;

#ifndef FALSE
#define FALSE  0
#endif

#ifndef TRUE
#define TRUE   (!FALSE)
#endif

enum PlatformStatus {
	PLATFORM_INIT_OK = 0x00,
	PLATFORM_NO_SD_LINK = 0x01,
	PLATFORM_CHECK_MFI_FAILED = 0x02
};

bool isNwdAmProtocol(){
	char custom_id[92];
	__system_property_get("sys.suding.custom", custom_id);
	if (strcmp(custom_id, "nwd_am") == 0) {
        return true;
	}
	return false;
}

bool isHctProtocol(){
	char custom_id[92];
	__system_property_get("sys.suding.custom", custom_id);
	if (strcmp(custom_id, "hengchangtong") == 0) {
        return true;
	}
	return false;
}

bool isXiaoQiangProtocol(){
	char platform[92];
	__system_property_get("ro.board.platform", platform);
	if (strcmp(platform, "bengal") == 0) {
        return true;
	}
	if (strcmp(platform, "trinket") == 0) {
        return true;
	}
	if (strcmp(platform, "parrot") == 0) {
        return true;
	}
	return true;
}

unsigned char ctoi(char c) {
	if ((c >= 'A') && ((c <= 'F')))
		return (c - 'A' + 0x0A);
	if ((c >= 'a') && ((c <= 'f')))
		return (c - 'a' + 0x0A);
	if ((c >= '0') && ((c <= '9')))
		return (c - '0' + 0x00);
	return 0;
}
unsigned char hex_char_to_byte(UINT8 ch) {
	UINT8 num = 0xFF;

	if ((ch >= '0') && (ch <= '9')) {
		num = ch - '0';
	} else if ((ch >= 'a') && (ch <= 'z')) {
		num = ch - 'a' + 10;
	} else if ((ch >= 'A') && (ch <= 'Z')) {
		num = ch - 'A' + 10;
	}

	return num;
}

UINT8 hex_chars_to_byte(UINT8 data[2]) {
	UINT8 m = hex_char_to_byte(data[0]);
	UINT8 l = hex_char_to_byte(data[1]);

	return ((m << 8) & 0xF0) | (l & 0x0F);
}

unsigned char hex_string_to_byte_array(UINT32 str_len, char *str,
		UINT8 *num_arr) {
	UINT32 n = 0;
	UINT8 num = 0;

	if (str_len < 2) {
		return FALSE;
	}
	while (n < str_len) {
		if ((num = hex_char_to_byte(str[n++])) == 0xFF) {
			return FALSE;
		}
		*num_arr = num << 4;
		if ((num = hex_char_to_byte(str[n++])) == 0xFF) {
			return FALSE;
		}
		*num_arr |= num;
		num_arr++;
	}

	return TRUE;
}

unsigned char byte_array_to_hex_string(UINT8 *str, UINT8 *arr, UINT32 len) {
	UINT32 off = 0;

	if (!str || !arr || !len) {
		return FALSE;
	}
	while (off < len) {
		sprintf((char *) (str + (off * 2)), "%02X", arr[off]);
		off++;
	}

	return TRUE;
}

static char* start_with(char*data, char* str) {
	if ('\0' == *str)
		return NULL;
	char* pos = data;
	char* sub = str;
	while (*sub == *pos && *sub != '\0') {
		++sub;
		++pos;
	}
	if (*sub == '\0') {
		return pos;
	} else {
		return NULL;
	}
}

void timer_bt_disconnect_func(int n) {
	LOGV(
			"timer_bt_disconnect_func g_iap_status = %d g_bt_status=%d\n", g_iap_status, g_bt_status);
	if (g_bt_status == 1) {
		write_at_cmd("AT#CD");
	}
}

void timer_iap_connect_func(int n) {
	LOGV(
			"timer_iap_connect_func g_iap_status = %d g_bt_status=%d\n", g_iap_status, g_bt_status);
	if (g_iap_status != 1 && g_bt_status == 1) {
		connect_iap(g_remote_addr);
	}
}

void init_time(int time) {
	struct itimerval val;

	val.it_value.tv_sec = time; //2缁夋帒鎮楅崥顖滄暏鐎规碍妞傞崳锟�
	val.it_value.tv_usec = 0;

	val.it_interval.tv_sec = 0;
	val.it_interval.tv_usec = 0;

	setitimer(ITIMER_REAL, &val, NULL);
	LOGV("init_time time=%d\n", time);
}

int write_bt_addr_to_hostap() {
	//  /data/local/tmp/suding/bt_addr.conf
	struct sockaddr_un addr;
	int fd;
	char sock_path[128] = { "/dev/socket/sd_carplay" };
	const char *config_dir;

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);

	if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
		LOGV("sd_carplay no run\n");
		close(fd);
		return PLATFORM_NO_SD_LINK;
	}

	char buffer[40] = { 0 };
	strcpy(buffer, "AT#CN");
	strcat(buffer, g_local_addr);
	strcat(buffer, g_local_dev_id);
	strcat(buffer, "\r\n");
	write(fd, buffer, strlen(buffer));

	int len = read(fd, buffer, sizeof(buffer) - 1);
	if (len > 0 && strcmp(buffer, "OKCN\r\n") == 0) {
	}

	close(fd);
	return 0;
}

int write_at_cmd(char *data) {
	if (s_client_id <= 0)
		return 0;

	char cmd[1024] = { 0 };
	strcpy(cmd, data);
	strcat(cmd, "\r\n");

	write(s_client_id, cmd, strlen(cmd));
	LOGV("write_at_cmd len=%d::%s\n", strlen(cmd), cmd);
	return strlen(data);
}


int save_mac_to_file(const char *filepath, const uint8_t address[6]) {
    FILE *fd = fopen(filepath, "w");  // "w" 覆盖写, 如果需要追加改成 "a"
    if (!fd) {
        perror("fopen");
        return -1;
    }

    // 生成字符串 bt_addr=12:34:56:78:9A:BC
    char mac_str[32] = { 0 };
    int len = snprintf(mac_str, sizeof(mac_str),
                       "bt_addr=%02X:%02X:%02X:%02X:%02X:%02X",
                       address[0], address[1], address[2],
                       address[3], address[4], address[5]);

    // 写入文件
    if (fwrite(mac_str, 1, len, fd) != (size_t)len) {
        perror("fwrite");
        fclose(fd);
        return -1;
    }

    fclose(fd);
    return 0;
}
//
//int main() {
//    uint8_t address[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
//    if (save_mac_to_file("/system/etc/deviceinfo.ini", address) == 0) {
//        printf("MAC 地址保存成功\n");
//    } else {
//        printf("保存失败\n");
//    }
//    return 0;
//}


void inqury_bt_info() {
	if (s_client_id <= 0)
		return;

	char custom_id[92];
	__system_property_get("sys.suding.custom", custom_id);
	if (strcmp(custom_id, "nwd_am") == 0) {
		write_at_cmd("AT#MY"); //inquery bt version
		write_at_cmd("AT#DF"); //rf_serial check the local addr
		write_at_cmd("AT#MM"); //rf_serial check the local name
		LOGV("customer is nwd_am \n");
	}
	else if(isXiaoQiangProtocol()){
		write_at_cmd("AT#HR"); //inquery bt version
		write_at_cmd("AT#VR"); //inquery bt version
		write_at_cmd("AT#IR"); //inquery bt version
	}
	else{
		write_at_cmd("AT#QV"); //inquery bt version
		write_at_cmd("AT#VE"); //rf_serial check the local addr
		write_at_cmd("AT#QN"); //rf_serial check the local name
	}

}


static void on_at_iap_command() {
	char * data;
	static char pair_status = -1;
	if ((data = start_with(iap_buffer, "IA")) != NULL
			|| (data = start_with(iap_buffer, "DT")) != NULL) {
		g_bt_status = 0;
		LOGV("bt disconnect\n");
		__system_property_set("sys.bluetooth.connect.status", "0");
		on_bluetooth_connect_state(0);
		if (g_iap_status == 1) {
			disconnect_iap();
		}
		g_pair_status = 0;
		strcpy(g_remote_addr, "");
		g_support_iap = 0;
		g_iap_status = 0;
		g_AA_rfcomm_status = 0;
	} else if ((data = start_with(iap_buffer, "IB")) != NULL) {
		g_bt_status = 1;
		g_iap_status = 0;
		LOGV("bt connected\n");
		__system_property_set("sys.bluetooth.connect.status", "1");
		on_bluetooth_connect_state(1);
	} else if ((data = start_with(iap_buffer, "AA")) != NULL) {
		if (g_AA_rfcomm_status == 0) {

			if(s_client_id < 0 && iap_rfcomm_socket < 0)
			{
				if (open_iap_rfcomm() != 0) {
					//open bt failed
				}
			}

			if(iap_rfcomm_socket > 0)
		    {
				LOGV("start connect AA rfcomm \n");
				write(iap_rfcomm_socket,g_remote_addr,strlen(g_remote_addr));
		    }

			LOGV("bt wireless android auto connectting\n");
			// notify app connect
			char bd_addr[6];
			LOGV("bt androidauto connectted\n");
			int i;
			for (i = 0; i < 6; i++) {
				bd_addr[i] = ctoi(g_remote_addr[i * 2]) * 16
						+ ctoi(g_remote_addr[i * 2 + 1]);
			}

			LOGV(
					"start connect androidauto:%02X:%02X:%02X:%02X:%02X:%02X  bt_iap=%d\n", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5], 0);
			connect_androidauto_wl(bd_addr, g_local_addr, 0);
		} else {
			LOGV(
					"bt wireless android auto connected g_AA_rfcomm_status=%d\n", g_AA_rfcomm_status);
		}
		g_AA_rfcomm_status = 1;

	} else if ((data = start_with(iap_buffer, "JH")) != NULL) {
		strcpy(g_remote_addr, data);
		LOGV("bt g_remote_addr:%s s_client_id=%d\n", data, s_client_id);
		if (s_client_id <= 0) {
			open_bt_uart();
		}

		if (s_client_id > 0) {
			if (g_support_iap == 1 && g_iap_status == 0) {
				g_iap_status = 2;
				inqury_bt_info();
				connect_iap(g_remote_addr);
				signal(SIGALRM, timer_iap_connect_func);
				init_time(2);
			}
		} else {
			//if (open_iap_rfcomm() != 0) {
				//open bt failed
			//}
		}

		if (iap_rfcomm_socket > 0) {
			if (g_support_iap == 1 && g_iap_status == 0) {
				LOGV("start connect iap rfcomm 000\n");
				g_iap_status = 2;
				write(iap_rfcomm_socket, g_remote_addr, strlen(g_remote_addr));
			}
		}
	} else if ((data = start_with(iap_buffer, "SA")) != NULL) {
		strcpy(g_remote_name, data);
		LOGV("bt g_remote_name:%s\n", data);
		on_phone_bluetooth_name(data);
	} else if ((data = start_with(iap_buffer, "NA")) != NULL) //local name
	{
		strcpy(g_local_name, data);
		LOGV("at recv g_local_name:%s\n", g_local_name);
		__system_property_set("persist.bluetooth.local.name", g_local_name);
	} else if ((data = start_with(iap_buffer, "BV")) != NULL) //bt version
	{
		strcpy(g_bt_version, data);
		LOGV("at recv g_bt_version:%s\n", g_bt_version);
	}
	else if ((data = start_with(iap_buffer, "DB")) != NULL) //bt local bd
	{
		strcpy(g_local_addr, data);

		uint8_t bd_addr_local[6] = { 0 };
		int i = 0;
		for (i = 0; i < 6; i++) {
			bd_addr_local[i] = ctoi(g_local_addr[i * 2]) * 16
					+ ctoi(g_local_addr[i * 2 + 1]);
		}
		save_mac_to_file("/data/shark/deviceinfo.ini",bd_addr_local);
		write_bt_addr_to_hostap();
		// 020D7A424292
		LOGV("at recv g_local_addr:%s\n", g_local_addr);
	}
	else if (isNwdAmProtocol() && (data = start_with(iap_buffer, "IZ")) != NULL) //bt local bd
	{
		strcpy(g_local_addr, data);
		write_bt_addr_to_hostap();

		LOGV("at recv g_local_addr:%s\n", g_local_addr);
	}
	else if ((data = start_with(iap_buffer, "SS")) != NULL) {
		g_iap_status = 0;
		g_AA_rfcomm_status = 0;
		LOGV("bt iap disconnect iap_rfcomm_socket = %d \n",iap_rfcomm_socket);
		if (iap_rfcomm_socket > 0) {
			close_iap_rfcomm();
		}
	} else if (((data = start_with(iap_buffer, "SV")) != NULL)||(isNwdAmProtocol() && ((data = start_with(iap_buffer, "SPC")) != NULL))) {
		if (g_AA_rfcomm_status == 0) {
			char bd_addr[6];
			g_iap_status = 1;
			char bt_iap = 0;
			LOGV("bt iap connectted\n");
			int i;
			for (i = 0; i < 6; i++) {
				bd_addr[i] = ctoi(g_remote_addr[i * 2]) * 16
						+ ctoi(g_remote_addr[i * 2 + 1]);
			}
			if (g_pair_status
					== 1 /*&& strncmp(g_remote_addr,g_pair_addr,12) == 0*/) {
				bt_iap = 1;
			}
			g_pair_status = 0;
			LOGV(
					"start connect wireless carplay:%02X:%02X:%02X:%02X:%02X:%02X  bt_iap=%d\n", bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5], bt_iap);
			connect_carplay_wl(bd_addr, g_local_addr, bt_iap); //TODO
		}
		else
		{
			LOGV("bt wireless android auto connected g_AA_rfcomm_status=%d\n", g_AA_rfcomm_status);
		}
	} else if (((data = start_with(iap_buffer, "SI")) != NULL)) {
		LOGV("at recv iap data:%s\n", data);

		int len;
		len = strlen(data) / 2;
		if (len >= 1 && (strlen(data) % 2 == 0)) {
			char *arr = (char*) malloc(len);
			memset(arr, 0, len);
			hex_string_to_byte_array(strlen(data), data, (unsigned char*) arr);

			if (g_AA_rfcomm_status) {
				androidauto_readIap2DataProc(arr, len);
			} else {
				carplay_readIap2DataProc(arr, len);
			}
			free(arr);
		}
	}else if((isNwdAmProtocol()&&(data = start_with(iap_buffer, "SPD")) != NULL)){
		data = data+1;
		LOGV("at recv iap data:%s\n", data);
		int len;
		len = strlen(data) / 2;
		if (len >= 1 && (strlen(data) % 2 == 0)) {
			char *arr = (char*) malloc(len);
			memset(arr, 0, len);
			hex_string_to_byte_array(strlen(data), data, (unsigned char*) arr);

			if (g_AA_rfcomm_status) {
				androidauto_readIap2DataProc(arr, len);
			} else {
				carplay_readIap2DataProc(arr, len);
			}
			free(arr);
		}
	} else if ((data = start_with(iap_buffer, "ZB")) != NULL) {
		LOGV("at recv auto rfcomm data:%s\n", data);

		int len;
		len = strlen(data) / 2;
		if (len >= 1 && (strlen(data) % 2 == 0)) {
			char *arr = (char*) malloc(len);
			memset(arr, 0, len);
			hex_string_to_byte_array(strlen(data), data, (unsigned char*) arr);

			if (g_AA_rfcomm_status) {
				androidauto_readIap2DataProc(arr, len);
			} else {
				carplay_readIap2DataProc(arr, len);
			}
			free(arr);
		}
	} else if ((data = start_with(iap_buffer, "US")) != NULL) {
		LOGV("at rec UUID start\n");
		memset(g_remote_phone_uuid, 0, MAX_BT_INFO);
	} else if ((data = start_with(iap_buffer, "UU")) != NULL) {
		strcat(g_remote_phone_uuid, data);
		strcat(g_remote_phone_uuid, " ");
	} else if ((data = start_with(iap_buffer, "UE")) != NULL) {
		LOGV("at recv UUID end \n");
		LOGV("at recv UUID g_remote_phone_uuid:%s \n", g_remote_phone_uuid);
		if (NULL != strstr(g_remote_phone_uuid, IAP_UUID)) {
			g_support_iap = 1;
			LOGV("s_client_id=%d iap_rfcomm_socket=%d g_bt_status=%d g_remote_addr:%s g_iap_status=%d\n", s_client_id, iap_rfcomm_socket,g_bt_status, g_remote_addr, g_iap_status);
			if (s_client_id > 0 && g_bt_status == 1
					&& strlen(g_remote_addr) == 12 && g_iap_status == 0) {
				LOGV("start connect iap virtual uart\n");
				g_iap_status = 2;
				inqury_bt_info();
				connect_iap(g_remote_addr);
				signal(SIGALRM, timer_iap_connect_func);
				init_time(2);
			}

			if(s_client_id < 0 && iap_rfcomm_socket < 0)
			{
				if (open_iap_rfcomm() != 0) {
					//open bt failed
				}
			}

			if (iap_rfcomm_socket > 0 && g_bt_status == 1
					&& strlen(g_remote_addr) == 12 && g_iap_status == 0) {
				LOGV("start connect iap rfcomm 111\n");
				g_iap_status = 2;
				write(iap_rfcomm_socket, g_remote_addr, strlen(g_remote_addr));
			}
		} else {
			//g_pair_status = 0;
		}
	} else if ((data = start_with(iap_buffer, "P0")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 0;
		LOGV("bt pair_status = %d g_pair_addr:%s\n", pair_status, data);
	} else if ((data = start_with(iap_buffer, "P1")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 1;
		g_pair_status = 1;
		LOGV("bt pair_status = %d g_pair_addr:%s\n", pair_status, data);
	} else if ((data = start_with(iap_buffer, "P2")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 2;
		g_pair_status = 0;
		LOGV("bt pair_status = %d g_pair_addr:%s\n", pair_status, data);
	} else if ((data = start_with(iap_buffer, "P3")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 3;
		LOGV("bt g_pair_status = %d g_pair_addr:%s\n", g_pair_status, data);
	}
	else if (isNwdAmProtocol() && (data = start_with(iap_buffer, "PR0")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 0;
		LOGV("bt pair_status = %d g_pair_addr:%s\n", pair_status, data);
	}
	else if (isNwdAmProtocol() && (data = start_with(iap_buffer, "PR1")) != NULL) {
		strcpy(g_pair_addr, data);
		pair_status = 1;
		g_pair_status = 1;
		LOGV("bt pair_status = %d g_pair_addr:%s\n", pair_status, data);
	}
	else if (isXiaoQiangProtocol() && (data = start_with(iap_buffer, "IS")) != NULL) {
		LOGV("Tinker bt pair_status = %d g_pair_addr:%s \n", pair_status, data);
		char phoneType [20];
		char paired [20];
		char macAddr [20];
		memset(macAddr,0,20);
		memset(phoneType,0,20);
		memset(paired,0,20);

		strncpy(phoneType, data, 1);
		strncpy(paired, data+1, 1);
		strncpy(macAddr, data+2, 12);

		strcpy(g_pair_addr, macAddr);
		strcpy(g_remote_addr, macAddr);

        char bd_addr[6];
		int i;
		for (i = 0; i < 6; i++) {
			bd_addr[i] = ctoi(g_remote_addr[i * 2]) * 16
					+ ctoi(g_remote_addr[i * 2 + 1]);
		}

		LOGV("bt bd_addr = %02X %02X %02X %02X %02X %02X \n",
				bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],
				bd_addr[5]);

		pair_status = 1;
		g_pair_status = 1;
		LOGV("bt pair_status = %d g_pair_addr:%s \n", pair_status, macAddr);


        LOGV("VS = %s\n", iap_buffer);
        // VS0101GOC11
        int phone = atoi( phoneType );
        LOGV("bt connected,phone = %d \n",phone);
        if(phone)
        {
            if (iap_rfcomm_socket < 0) {
                open_iap_rfcomm();
            }
            LOGV("bt connected\n");
            __system_property_set("sys.bluetooth.connect.status", "1");
            on_bluetooth_connect_state(1);

        	LOGV("bt connected,phone is iPhone \n");
        	connect_carplay_wl(bd_addr, g_local_addr, 1);
        }else{
        	LOGV("bt connected,phone is Android \n");
        	g_AA_rfcomm_status = 1;
            if (iap_rfcomm_socket < 0) {
                open_iap_rfcomm();
            }
            LOGV("bt connected\n");
            __system_property_set("sys.bluetooth.connect.status", "1");
            on_bluetooth_connect_state(1);
        	connect_androidauto_wl(bd_addr, g_local_addr, 0);
        }
	}
}

static void on_char_iap(char c) {
	if (iap_count + 2 == MAX_COMMAND_LENGTH) {
		iap_count = 0;
		return;
	}
	if ('\r' == c || '\n' == c) {
		if (iap_count == 0)
			return;
		iap_buffer[iap_count++] = '\0';
		LOGV(
				"carplay at command len = %d:%s\n", strlen(iap_buffer), iap_buffer);
		on_at_iap_command();
		iap_count = 0;
	} else {
		iap_buffer[iap_count++] = c;
	}
}

#define MAX_COMMAND_LENGTH 1024*4
static void *bt_AT_cmd_process(void *param_fd) {
	char buffer[MAX_COMMAND_LENGTH];
	long server = (long) param_fd;
	if (server <= 0) {
		return 0;
	}

	while (1) {
		if (!iap_running)
			break;
		memset(buffer, 0, MAX_COMMAND_LENGTH);
		int len = read(server, buffer, MAX_COMMAND_LENGTH);
		if (len <= 0) {
			usleep(500);
			continue;
		}
		LOGV("bt_AT_cmd_process: len = %d:%s\n", len, buffer);
		for (int i = 0; i < len; i++) {
			on_char_iap(buffer[i]);
		}
	}
	close(server);
	return NULL;
}

void timer_inquery_connect_func(int n)
{
    LOGV("timer_inquery_connect_func\n");
	inqury_bt_info();
	if(isNwdAmProtocol()){
//	  write_at_cmd("AT#MX0"); //inquery bt info
	  write_at_cmd("AT#QI"); //inquery bt info
	}
	else if (isXiaoQiangProtocol()){
		 write_at_cmd("AT#HR"); //inquery bt info
		 write_at_cmd("AT#VR"); //inquery bt info
		 write_at_cmd("AT#IR"); //inquery bt info
		 write_at_cmd("AT#VE"); //inquery bt info
	}
	else{
	  write_at_cmd("AT#QI"); //inquery bt info
	}
}

int open_bt_uart() {
//	if(isHctProtocol()){
//      return -1;
//	}

	int ret = -1;
	char uartval[50] = { 0 };
	struct termios tty;
	char buffer[MAX_COMMAND_LENGTH];
	LOGV("open_bt_uart start\n");

	if(isXiaoQiangProtocol())
	{
		strcpy(uartval, "/dev/zj_bt_serial");
	}
	else {
		strcpy(uartval, "/dev/rf_serial");
	}

	LOGV("Try to open port: %s.\n", uartval);
	int fd = open(uartval, O_RDWR | O_NOCTTY);
	if (fd <= 0) {
		LOGV("failed to open %s:%s.\n", uartval, strerror(errno));
		return -1;
	}
	/* Set raw attributes on the pty. */
	tcgetattr(fd, &tty);
	cfmakeraw(&tty);
	tcsetattr(fd, TCSAFLUSH, &tty);

	pthread_t thread;
	pthread_t tid;

	iap_running = 1;
	s_client_id = fd;
	ret = pthread_create(&tid, NULL, bt_AT_cmd_process, (void*) fd);
	if (ret != 0) {
		LOGV("create bt_AT_cmd_process thread error\n");
		return -1;
	}

	signal(SIGALRM, timer_inquery_connect_func);
	init_time(2);
	LOGV("open_bt_uart end\n");
	return 0;
}


int disconnect_bt() {
	if (s_client_id <= 0)
		return 0;

	if(isXiaoQiangProtocol()){
		write_at_cmd("AT#DR");
	}else{
		write_at_cmd("AT#CD");
	}
	signal(SIGALRM, timer_bt_disconnect_func);
	init_time(3);
	return 1;
}
int disconnect_iap() {
	if (s_client_id <= 0)
		return 0;

	if(isNwdAmProtocol()){
		write_at_cmd("AT#VH");
	}else{
		write_at_cmd("AT#SH");
	}
	return 1;
}
int connect_iap(char *bd) {
	if (s_client_id <= 0)
		return 0;

	char cmd[128] = { 0 };
	if (bd == NULL && strlen(bd) != 12)
		return 0;

	if(isNwdAmProtocol()){
	  strcpy(cmd, "AT#VF");
	}else{
	  strcpy(cmd, "AT#SP");
	}
	strcat(cmd, bd);
	strcat(cmd, "00000000DECAFADEDECADEAFDECACAFE");
	write_at_cmd(cmd);
	return 1;
}

#define MAX_SEND_LEN 200
int send_iap_data(char *data, int data_len) {
	LOGV("send_iap_data thread want enter s_client_id = %d \n",s_client_id);
	LOGV("send_iap_data thread want enter isXiaoQiangProtocol = %d \n",isXiaoQiangProtocol());
	LOGV("send_iap_data thread want enter iap_rfcomm_socket = %d \n",iap_rfcomm_socket);
	if (s_client_id <= 0 || isXiaoQiangProtocol()) {
		LOGV("send_iap_data thread enter\n");
		if (iap_rfcomm_socket > 0) {
			send_iap_data_socket(data, data_len);
		}
	} else {
		int ret;
		char *arr = (char*) malloc(data_len * 2 + 1);
		memset(arr, 0, data_len * 2 + 1);
		byte_array_to_hex_string((unsigned char*) arr, (unsigned char*) data,
				data_len);

		int len = strlen(arr);
		int send_times = len / MAX_SEND_LEN;
		int i = 0;
		char buff[1024] = { 0 };
		memset(buff, 0, 1024);
		if(isNwdAmProtocol()){
			for (i = 0; i < send_times; i++) {
				strcpy(buff, "AT#VG");
				strncat(buff, arr + i * MAX_SEND_LEN, MAX_SEND_LEN);
				write_at_cmd(buff);
				memset(buff, 0, 1024);
			}
			if ((strlen(arr) % MAX_SEND_LEN) > 0) {
				memset(buff, 0, 1024);
				strcpy(buff, "AT#VG");
				strncat(buff, arr + i * MAX_SEND_LEN, strlen(arr) % MAX_SEND_LEN);
				write_at_cmd(buff);
			}
			free(arr);
		}else{
			for (i = 0; i < send_times; i++) {
				strcpy(buff, "AT#SG");
				strncat(buff, arr + i * MAX_SEND_LEN, MAX_SEND_LEN);
				write_at_cmd(buff);
				memset(buff, 0, 1024);
			}
			if ((strlen(arr) % MAX_SEND_LEN) > 0) {
				memset(buff, 0, 1024);
				strcpy(buff, "AT#SG");
				strncat(buff, arr + i * MAX_SEND_LEN, strlen(arr) % MAX_SEND_LEN);
				write_at_cmd(buff);
			}
			free(arr);
		}

	}

	return data_len;
}

static void *iap_socket_process(void *param_fd) {
	char buffer[MAX_COMMAND_LENGTH];
	long server = (long) param_fd;
	if (server <= 0) {
		return 0;
	}

	int len = 0;
	int rc = 0;
	struct pollfd pfd;
	LOGV("iap_socket_process thread enter\n");

	while (1) {
		if (!iap_socket_running)
			break;

		pfd.fd = server;
		pfd.events = POLLIN | POLLHUP | POLLRDNORM;
		pfd.revents = 0;

		rc = poll(&pfd, 1, 100);
		if (rc == 0)
		{
			//timeout
			continue;
		}

		if(rc > 0)
		{
			len = read(server, buffer, MAX_COMMAND_LENGTH);
		}

		if (len <= 0) {
			break;
		}
		if (len > 0) {
			LOGV("carplay_readIap2DataProc len=%d\n", len);
			char tmp[4096] = { 0 };
			memset(tmp, 0, 4096);

			for (int i = 0; i < len; i++) {
				sprintf(tmp + i * 2, "%02X", buffer[i]);
			}
			LOGV("carplay_readIap2DataProc:%s\n", tmp);

			if (g_AA_rfcomm_status) {
				androidauto_readIap2DataProc(buffer, len);
			} else {
				carplay_readIap2DataProc(buffer, len);
			}
		}
	}
	LOGV("iap_socket_process exit\n");
	close(server);
	iap_rfcomm_socket = -1;
	return NULL;
}
int close_iap_rfcomm()
{
#if 1
	LOGV("close_iap_rfcomm\n");
	if(iap_rfcomm_socket > 0)
	{
		close(iap_rfcomm_socket);
	}
	iap_rfcomm_socket = -1;
	iap_socket_running = 0;
	return 0;
#endif
}
int open_iap_rfcomm() {
	int ret = 0;
	struct sockaddr_un addr;
	int fd;
//	char sock_path[128] = { "/dev/socket/goc_rfcom" };//hengchangtong
	char sock_path[128] = { "/dev/socket/zj_bt_socket" };//xiaoqiang
	const char *config_dir;

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);

	if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
//		LOGV("/dev/socket/goc_rfcom connect failed\n");
		LOGV("/dev/socket/zj_bt_socket failed\n");
		close(fd);
		return -1;
	}
//	LOGV("/dev/socket/goc_rfcom connect success\n");
	LOGV("/dev/socket/zj_bt_socket connect success\n");
	pthread_t thread;
	pthread_t tid;

	iap_socket_running = 1;
	iap_rfcomm_socket = fd;
	ret = pthread_create(&tid, NULL, iap_socket_process, (void*) fd);
	if (ret != 0) {
		close(fd);
		LOGV("create iap_socket_process thread error\n");
		return -1;
	}

	return 0;
}

int send_iap_data_socket(char *data, int data_len) {
	if (iap_rfcomm_socket > 0) {
		char buffer[4096] = { 0 };
		memset(buffer, 0, 4096);

		for (int i = 0; i < data_len; i++) {
			sprintf(buffer + i * 2, "%02X", data[i]);
		}
		LOGV("send_iap_data_socket:%s\n", buffer);

		write(iap_rfcomm_socket, data, data_len);
	}
	return data_len;
}

int write_local_addr_to_hostapp(char *data) {
	if (data == NULL)
		return 0;

	strcpy(g_local_addr, data);
	write_bt_addr_to_hostap();

	LOGV("write_local_write g_local_addr:%s\n", g_local_addr);
	return 0;
}
int write_local_dev_id_to_hostapp(char *data) {
	if (data == NULL)
		return 0;

	if (strlen(data) == 12) {
		strcpy(g_local_dev_id, data);
		LOGV(
				"write_local_dev_id_to_hostapp g_local_dev_id:%s\n", g_local_dev_id);
	}
	return 1;
}

int process_app_bt_cmd(char *data) {
	if (data == NULL)
		return 0;

	if (s_client_id <= 0) {
		LOGV("process_app_bt_cmd data:%s\n", data);
		for (int i = 0; i < strlen(data); i++) {
			on_char_iap(data[i]);
		}
	}
	return 1;
}

